home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / source / xdme_1.84_src.lha / XDME / Src / Mod / CmdSh.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-05  |  21.2 KB  |  784 lines

  1.  
  2. #define CMDSH_C 1
  3.  
  4. #define ACTION_FORCE 2001
  5.  
  6. /******************************************************************************
  7.  
  8.     MODULE
  9.     CMDSH.c
  10.  
  11.     DESCRIPTION
  12.     COMmand SHell for XDME
  13.  
  14.     NOTES
  15.  
  16.     BUGS
  17.     the "AbortPkt()" call does obviously not work, so the
  18.     Command Window should better be closed with a request out
  19.     of itself;
  20.     we are currently using ACTION_FORCE to satify our own
  21.     ACTION_READ-request, but that is a hack, since that action
  22.     is not documented in includes/dos/#?.h
  23.  
  24.     TODO
  25.     *fix bugs - which ?
  26.     *we should better use ACTION_WAIT_FOR_CHAR instead of the
  27.     ACTION_READ so we can control timeouts in order to update
  28.     the Prompt and to have a sure close-possibility.
  29.     *each time the selected prompt is changed, we should rewrite
  30.     it (e.g. l=ACTION_WAIT_FOR_CHAR(0); ACTION_FORCE(\n);
  31.      s=ACTION_READ(l); Write(\r); Write(Prompt); ACTION_FORCE(s);)
  32.     change of prompt may be: new prompt-template, any change
  33.     of prompted data (e.g. window, line, column, char,...)
  34.     reprompt should only be done in mainloop
  35.  
  36.     EXAMPLES
  37.  
  38.     SEE ALSO
  39.  
  40.     AUTHOR
  41.     Bernd "0" Noll (b_noll@informatik.uni-kl.de)
  42.  
  43.     HISTORY
  44.     13-09-94 b_noll created
  45.     14-09-94 b_noll command documentation, added Prompt
  46.     21-09-94 b_noll added DEFCMD/DEFHELP-support
  47.     01-10-94 b_noll introduced DEFMESSAGE
  48.     04-10-94 b_noll introduced format_string for prompt
  49.     03-12-94 b_noll removed 'defs.h'
  50.  
  51. ******************************************************************************/
  52.  
  53.  
  54. /**************************************
  55.           Includes
  56. **************************************/
  57.  
  58.  
  59. #include <exec/ports.h>
  60. #include <exec/memory.h>
  61. #include <utility/tagitem.h>
  62. #include <dos/dos.h>
  63. #include <dos/dosextens.h>
  64.  
  65. #include <proto/exec.h>
  66. #include <proto/dos.h>
  67.  
  68. /* #include "defs.h" */
  69.  
  70. #include  <stddef.h>
  71. #include "xdme_base.h"
  72.  
  73. /**************************************
  74.         Global Variables
  75. **************************************/
  76.  
  77. Prototype ULONG CMDSH_SigMask;
  78. Prototype UBYTE*CMDSH_FileName;
  79. Prototype UBYTE*CMDSH_Prompt;
  80. //Prototype UBYTE CMDSH_Active;
  81. //Prototype UBYTE CMDSH_ErrorsOut;
  82. //Prototype UBYTE CMDSH_WarningsOut;
  83.  
  84. /**************************************
  85.       Internal Defines & Structures
  86. **************************************/
  87.  
  88. #define CMDSH_OK      0
  89. #define CMDSH_NOFILE     -1
  90. #define CMDSH_NOTFOUND     -2
  91. #define CMDSH_FILEOPEN     -3
  92. #define CMDSH_NOPORT     -4
  93. #define CMDSH_NOTINTER     -5
  94. /* #define CMDSH_ */
  95.  
  96. #define CMDSH_BufferSize  MAXLINELEN
  97. DEFMESSAGE( _CMDSH_good_bye, "\nCommandshell is Closing!\n\f\n" )
  98. #define CMDSH_CloseMsg      "\n\n\f"
  99.  
  100.  
  101. #define DEF_FILENAME "CON:0/11/640/60/XDME Command Shell/Close"
  102. #define DEF_PROMPT   "XDME> "
  103.  
  104. /**************************************
  105.        Internal Variables
  106. **************************************/
  107.  
  108.  
  109. /* #undef  Local */
  110. /* #define Local */
  111.  
  112. Local struct MsgPort    *CMDSH_Port        = NULL;    /* Our ReplyMessagePort */
  113. Local UBYTE        *CMDSH_Buffer        = 0;    /* Needed for the ASynch IO */
  114. Local struct DosPacket    *CMDSH_Packet        = NULL;    /* Needed for the ASynch IO */
  115. Local BPTR         CMDSH_File        = 0L;    /* The file created by _Open() */
  116. Local UBYTE         CMDSH_Pending        = 0;    /*        Info about A Message is sent   */
  117. //    UBYTE           CMDSH_Active       = 0;      /* External info about A CmdShell is open  */
  118. //    UBYTE           CMDSH_ErrorsOut    = 0;      /* External_only! control if errors    shall be displayed on cmdshell */
  119. //    UBYTE           CMDSH_WarningsOut  = 0;      /* External_only! control if warnings shall be displayed on cmdshell */
  120. //    UBYTE         CMDSH_LoopUpdate   = 0;    /* Request to update the Prompt  */
  121.       ULONG         CMDSH_SigMask        = 0;    /* External info about 1<<_Port->mp_SigBit */
  122.       UBYTE        *CMDSH_FileName     = NULL;    /*        Info about which file to use   */
  123.       UBYTE        *CMDSH_Prompt        = NULL;    /*        Info about the File's prompt   */
  124.  
  125.  
  126. Local struct Message    *CMDSH_Message       = NULL; /* Shortcut to do2msg(CMDSH_Packet) */
  127. Local struct FileHandle *CMDSH_FileHandle  = NULL; /* Shortcut to (CMDSH_File<<2) */
  128. Local struct MsgPort    *CMDSH_FilePort    = NULL; /* Shortcut to (CMDSH_Filehandle->fh_Type) */
  129.  
  130. /**************************************
  131.        Internal Prototypes
  132. **************************************/
  133.  
  134. void CMDSH_Update(void);
  135.  
  136. /**************************************
  137.          Macros
  138. **************************************/
  139.  
  140. #define do2msg(pkt) ((struct Message *)(((ULONG)(pkt)) - offsetof (struct StandardPacket, sp_Pkt)))
  141.  
  142. /**************************************
  143.          Implementation
  144. **************************************/
  145.  
  146.  
  147.  
  148.  
  149.  
  150. int CMDSH_Send (void) {
  151.  
  152.     /* ---- safety check */
  153.     if (!CMDSH_File)
  154.     return CMDSH_NOFILE;
  155.  
  156.     /* ---- Show the prompt */
  157.     CMDSH_Update();
  158.     // FPuts(CMDSH_File, CMDSH_Prompt);
  159.     // Flush(CMDSH_File);
  160.  
  161.     /* ---- [re]init the packet */
  162.     CMDSH_Packet->dp_Type = ACTION_READ;
  163.     CMDSH_Packet->dp_Arg1 = CMDSH_FileHandle->fh_Arg1;
  164.     CMDSH_Packet->dp_Arg2 = (LONG)CMDSH_Buffer;
  165.     CMDSH_Packet->dp_Arg3 = CMDSH_BufferSize;
  166.  
  167.     /* ---- send the packet */
  168.     /* CMDSH_Message->mn_ReplyPort = CMDSH_Packet->dp_Port = CMDSH_Port; */
  169.     /* PutMsg (CMDSH_FilePort, CMDSH_Message); */
  170.     SendPkt(CMDSH_Packet, CMDSH_FilePort, CMDSH_Port);
  171.  
  172.     CMDSH_Pending = 1;
  173. } /* CMDSH_Send */
  174.  
  175. int CMDSH_CloseShell (void) {
  176.  
  177.     /* ---- safety check */
  178.     if (!CMDSH_File)
  179.     return CMDSH_NOFILE;
  180.  
  181.     /* ---- abort the current packet */
  182.     if (CMDSH_Pending) {
  183.     ULONG //signals,
  184.           oldsigs;
  185.     struct DosPacket *dp2;
  186.     oldsigs = SetSignal(0L, SIGF_DOS);
  187.  
  188.     /* ---- satisfy the READ-Packet */
  189.     dp2 = AllocDosObject (DOS_STDPKT, NULL);
  190.     if (dp2) {
  191.         dp2->dp_Type = ACTION_FORCE; /* ****That action is not noted in the includes**** */
  192.         dp2->dp_Arg1 = CMDSH_FileHandle->fh_Arg1;
  193.         dp2->dp_Arg2 = (LONG)  CMDSH_CloseMsg;
  194.         dp2->dp_Arg3 = sizeof (CMDSH_CloseMsg);
  195.  
  196.         SendPkt(dp2, CMDSH_FilePort, CMDSH_Port);
  197.         Remove(&WaitPort(CMDSH_Port)->mn_Node);
  198.         //GetMsg(CMDSH_Port);
  199.     } /* if */
  200.  
  201.     /* ---- Break the read Packet */
  202.     /*    the AbortPkt() is probably not neccessary since we are now */
  203.     /*    satisfying our own READ-request w/ FORCE (s.a.) */
  204.     // AbortPkt(CMDSH_FileHandle->fh_Type, CMDSH_Packet);
  205.  
  206.  
  207.     /* ---- wait for the packet to be replied */
  208. #if 0
  209.     signals = Wait(SIGF_DOS| (1 << CMDSH_Port->mp_SigBit));
  210.     if (signals & SIGF_DOS)
  211.         GetMsg  (CMDSH_Port);
  212.     else {
  213.         struct Process *pr;
  214.         pr = (void *)FindTask(NULL);
  215.         GetMsg (&pr->pr_MsgPort);
  216.     } /* if */
  217. #else
  218.     Remove(&WaitPort(CMDSH_Port)->mn_Node);
  219.     //GetMsg(CMDSH_Port);
  220. #endif
  221.     if (dp2)
  222.         FreeDosObject(DOS_STDPKT, dp2);
  223.  
  224.     oldsigs = SetSignal(oldsigs, SIGF_DOS);
  225.     CMDSH_Pending = 0;
  226.     } /* if */
  227.  
  228.     /* ---- Close the file */
  229.     if (CMDSH_File)
  230.     Close (CMDSH_File);
  231.     CMDSH_File         = 0;
  232.  
  233.     /* ---- clear all file data */
  234.     CMDSH_Active     = 0;
  235.     CMDSH_FileHandle = NULL;
  236.     CMDSH_FilePort   = NULL;
  237.  
  238.     return CMDSH_OK;
  239. } /* CMDSH_CloseShell */
  240.  
  241. int CMDSH_OpenShell (const UBYTE *filename) {
  242.  
  243.     /* ---- safety check */
  244.     if (!CMDSH_Port)
  245.     return CMDSH_NOPORT;
  246.  
  247.     if (CMDSH_File)
  248.     return CMDSH_FILEOPEN;
  249.  
  250.     /* ---- Open the file */
  251.     CMDSH_File = Open(filename, MODE_OLDFILE);
  252.     if (!CMDSH_File)
  253.     return CMDSH_NOTFOUND;
  254.  
  255.     /* ---- safety check */
  256.     if (!IsInteractive(CMDSH_File)) {
  257.     Close (CMDSH_File);
  258.     CMDSH_File = NULL;
  259.     return CMDSH_NOTINTER;
  260.     } /* if */
  261.  
  262.     /* ---- [re]init all file data */
  263.     CMDSH_Active     = 1;
  264.     CMDSH_FileHandle = BADDR(CMDSH_File);
  265.     CMDSH_FilePort   = CMDSH_FileHandle->fh_Type;
  266.  
  267.     /* ---- prompt for input */
  268.     CMDSH_Send();
  269.  
  270.     return CMDSH_OK;
  271. } /* CMDSH_OpenShell */
  272.  
  273.  
  274. /*************************************************
  275.     Entry & Exit Code
  276. *************************************************/
  277.  
  278.  
  279. DEFAUTOEXIT( CMDSH_Terminate )
  280. {
  281.     /* ---- close the file */
  282.     CMDSH_CloseShell();
  283.  
  284.     /* ---- free all permanent data */
  285.     if (CMDSH_Packet)
  286.     FreeDosObject(DOS_STDPKT, CMDSH_Packet);
  287.     CMDSH_Packet = NULL;
  288.  
  289.     if (CMDSH_Buffer)
  290.     FreeMem(CMDSH_Buffer, CMDSH_BufferSize);
  291.     CMDSH_Buffer = NULL;
  292.  
  293.     if (CMDSH_Port)
  294.     DeleteMsgPort(CMDSH_Port);
  295.     CMDSH_Port = NULL;
  296.  
  297.     if (CMDSH_FileName)
  298.     free(CMDSH_FileName);
  299.     CMDSH_FileName = NULL;
  300.  
  301.     if (CMDSH_Prompt)
  302.     free(CMDSH_Prompt);
  303.     CMDSH_Prompt = NULL;
  304.  
  305. } /* CMDSH_Terminate */
  306.  
  307.  
  308. DEFAUTOINIT( CMDSH_Initialize )
  309. {
  310. //puts (__FILE__);
  311.     /* ---- allocate all permanent data */
  312.     CMDSH_Packet   = AllocDosObject(DOS_STDPKT, NULL);
  313.     CMDSH_Port       = CreateMsgPort();
  314.     CMDSH_Buffer   = AllocMem(CMDSH_BufferSize, MEMF_PUBLIC); /* _MUST_ be public Memory! */
  315.     CMDSH_FileName = strdup(DEF_FILENAME);
  316.     CMDSH_Prompt   = strdup(DEF_PROMPT);
  317.  
  318.     /* ---- safety check */
  319.     if (!CMDSH_Packet || !CMDSH_Port || !CMDSH_Buffer || !CMDSH_FileName || ! CMDSH_Prompt) {
  320.     CMDSH_Terminate();
  321. // --- in fact, this should be 'return -1', but we do not want to break autoinit
  322.     return;
  323.     } /* if */
  324.  
  325.     /* ---- init the known shortcuts */
  326.     CMDSH_Message = do2msg(CMDSH_Packet);
  327.     CMDSH_SigMask = 1 << CMDSH_Port->mp_SigBit;
  328.  
  329. } /* CMDSH_Initialize */
  330.  
  331. /*************************************************
  332.     Application Interface
  333. *************************************************/
  334.  
  335. /*
  336. ** Explain an CMDSH related error
  337. */
  338. int CMDSH_Error (int number, const UBYTE *command, ...) {
  339.     switch (number) {
  340.     case CMDSH_OK:
  341.     return RET_SUCC;
  342.     case CMDSH_NOTFOUND:
  343. DEFMESSAGE( _CMDSH_cant_open_cmdsh_file, "%s:\nFile `%s' not found!" )
  344.     error (_CMDSH_cant_open_cmdsh_file, command, CMDSH_FileName);
  345.     break;
  346.     case CMDSH_NOFILE:
  347. DEFMESSAGE( _CDMSH_cmdshell_not_open, "%s:\nCommand Shell not open!" )
  348.     error (_CDMSH_cmdshell_not_open, command);
  349.     break;
  350.     case CMDSH_NOPORT:
  351. DEFMESSAGE( _CMDSH_cmdsh_module_inactive, "%s:\nCommand Shell Module not active!" )
  352.     error (_CMDSH_cmdsh_module_inactive, command);
  353.     break;
  354.     case CMDSH_FILEOPEN:
  355. DEFMESSAGE( _CMDSH_only_one_cmdsh, "%s:\nCommand Shell is already open!" )
  356.     error (_CMDSH_only_one_cmdsh, command);
  357.     break;
  358.     case CMDSH_NOTINTER:
  359. DEFMESSAGE( _CMDSH_cmdsh_file_noninteractive, "%s:\nFile `%s' is not interactive!" )
  360.     error (_CMDSH_cmdsh_file_noninteractive, command, CMDSH_FileName);
  361.     break;
  362.     default:
  363. DEFMESSAGE( _CMDSH_internal_error, "%s:\nCommand Shell Internal Error!" )
  364.     error (_CMDSH_internal_error, command);
  365.     } /* switch */
  366.     return RET_FAIL;
  367. } /* CMDSH_Error */
  368.  
  369. /*
  370. **  Get a packet from the Commandshell
  371. */
  372. Prototype void    CMDSH_Control     (void);
  373. void CMDSH_Control (void) {
  374.     struct Message *msg;
  375.     msg = GetMsg(CMDSH_Port);
  376.     if (msg != (void *)CMDSH_Message) {
  377.     /* ---- not our packet? */
  378.     if (msg)
  379.         ReplyMsg(msg);
  380.     } else {
  381.     LONG len; // err;
  382.     CMDSH_Pending     = 0;
  383.     len         = CMDSH_Packet->dp_Res1;
  384. //    err         = CMDSH_Packet->dp_Res2;
  385.     CMDSH_Buffer[len] = 0;
  386.     if (!len) {
  387.         /* ---- user selected Close in the shell? */
  388.         CMDSH_CloseShell();
  389.     } else {
  390.  
  391. //          UBYTE inter = (CMDSH_ErrorsOut?1:0) | (CMDSH_WarningsOut?2:0);
  392. //          CMDSH_ErrorsOut = CMDSH_WarningsOut = 1;
  393.  
  394.         /* ---- strip ending NewLine */
  395.         while ((--len >= 0) && (CMDSH_Buffer[len] == '\n'))
  396.         CMDSH_Buffer[len] = 0;
  397.  
  398.         /* ---- execute the command */
  399.         do_command(CMDSH_Buffer);
  400.  
  401. //          CMDSH_ErrorsOut    = 1 && (inter & 1);
  402. //          CMDSH_WarningsOut = 1 && (inter & 2);
  403.  
  404.         /* ---- prompt for the next input */
  405.         if (CMDSH_File) {
  406.         CMDSH_Send();
  407.         } /* if !terminated */
  408.     } /* if !eof */
  409.     } /* if is_cmdmsg */
  410. } /* CMDSH_Control */
  411.  
  412. /*
  413. **  Redisplay the prompt on the Commandshell
  414. */
  415. void CMDSH_Update (void) {
  416. //    char *inter1, *inter2, *inter3, *inter4, quoted;
  417.  
  418.     /* SHORTER/BETTER: */
  419.     /* FLEXPRINTF(CMDSH_File, FPuts, CMDSH_Prompt, NULL, mygetvar); */
  420.     /* OR: */
  421.     format_string (tmp_buffer, CMDSH_Prompt);
  422.     FPuts   (CMDSH_File, tmp_buffer);
  423.     Flush   (CMDSH_File);
  424.  
  425. #if 0
  426.     inter1 = inter3 = strdup (CMDSH_Prompt);
  427.     if (!inter1) {
  428.     FPuts    (CMDSH_File, CMDSH_Prompt);
  429.     Flush    (CMDSH_File);
  430.     nomemory();
  431.     return;
  432.     } /* if */
  433.  
  434.     inter2 = breakout(&inter1, "ed, &inter4);
  435.     if (*inter1) {/* Not enclosed w/ brackets */
  436.  
  437.     FPuts    (CMDSH_File, CMDSH_Prompt);
  438.     Flush    (CMDSH_File);
  439.     } else {
  440.     FPuts    (CMDSH_File, inter2);
  441.     Flush    (CMDSH_File);
  442.     } /* if */
  443.     if (inter4)
  444.     free(inter4);
  445.     free(inter2);
  446. #endif
  447.  
  448. } /* CMDSH_Update */
  449.  
  450. /*
  451. **  Make some Output on the Cmdshell
  452. **  after that redisplay the prompt
  453. */
  454. Prototype int    CMDSH_Print     (const char *, ULONG *);
  455. int CMDSH_Print (const char *fmt, ULONG *va) {
  456.     if (!CMDSH_File)
  457.     return CMDSH_NOFILE;
  458.  
  459.     if (CMDSH_Pending) {
  460.     /* CMDSH_BufferInput(); */
  461.     FPuts (CMDSH_File, "\n");
  462.     } /* if */
  463.     VFPrintf  (CMDSH_File, fmt, va);
  464.     {
  465.     int len;
  466.     len = strlen(fmt);
  467.     if (len && (fmt[len-1] != '\n'))
  468.         FPuts (CMDSH_File, "\n");
  469.     }
  470.  
  471.     if (CMDSH_Pending) {
  472.     CMDSH_Update();
  473.     /* CMDSH_UnbufferInput(); */
  474.     } /* if */
  475.  
  476.     return CMDSH_OK;
  477. } /* CMDSH_Print */
  478.  
  479.  
  480. /*************************************************
  481.     Fragments of other modules
  482. *************************************************/
  483.  
  484. /* the line comments are just hints, where to
  485. ** look, they cannot be considered staying fixed */
  486.  
  487. #ifdef MAIN_C
  488.  
  489. DEFSIGHANDLER( CMDSH_SigMask, CMDSH_Control(); )
  490. DEFDEFINITION( PATCH_COMMANDSHELL 1 )
  491.  
  492. #endif
  493.  
  494. #ifdef WIN_C
  495.  
  496. /* line 1417/error */
  497. #ifdef PATCH_COMMANDSHELL
  498.     if (CMDSH_Active && CMDSH_ErrorsOut) {
  499.     va_start (va, fmt);
  500.     CMDSH_Print(fmt, (ULONG *)va);
  501.     va_end (va);
  502.     } /* if */
  503. #endif
  504.  
  505. /* line 1440/warn */
  506. #ifdef PATCH_COMMANDSHELL
  507.     if (CMDSH_Active && CMDSH_WarningsOut) {
  508.     va_start (va, fmt);
  509.     CMDSH_Print(fmt, (ULONG *)va);
  510.     va_end (va);
  511.     } /* if */
  512. #endif
  513.  
  514. #endif
  515.  
  516.  
  517. /*************************************************
  518.         XDME Command Interface
  519. *************************************************/
  520.  
  521. /*DEFHELP #cmd special COMMANDSHELL - The CommandShell Interface */
  522.  
  523. /*
  524. *!
  525. *! >CLOSECMDSHELL
  526. *!
  527. *!  Close the Commandshell Window.
  528. *!
  529. *  Please note, that currently it is _not_ _safe_
  530. *  to call that commando from elsewhere than the CommandShell
  531. *  itself.
  532. *
  533. */
  534. DEFUSERCMD("closecmdshell",  0, CF_COK|CF_ICO|CF_VWM, int, do_closecmdshell, (void), ;)
  535. /*DEFHELP #cmd commandshell CLOSECMDSHELL - close the command shell */
  536. Prototype int do_closecmdshell (void);
  537. int do_closecmdshell (void) {
  538. //    if (!CMDSH_Pending)
  539.       return CMDSH_Error( CMDSH_CloseShell(), av[0]);
  540. //    error ("%s:\n`%s' currently can be used only\nfrom _within_ the Commandshell!\n", av[0], av[0]);
  541. //    return RET_FAIL;
  542. } /* do_closecmdshell */
  543.  
  544. /*
  545. *!
  546. *! >OPENCMDSHELL
  547. *!
  548. *!  Open the Commandshell
  549. *!
  550. *!  Please Note, that only one Commandshell can be open
  551. *!  at a time.
  552. *!
  553. */
  554. DEFUSERCMD("opencmdshell",   0, CF_COK|CF_ICO|CF_VWM, int, do_opencmdshell,  (void), ;)
  555. /*DEFHELP #cmd commandshell OPENCMDSHELL - open the command shell with the filename in $CMDSHELLNAME */
  556. Prototype int do_opencmdshell (void);
  557. int do_opencmdshell (void) {
  558.     return CMDSH_Error( CMDSH_OpenShell(CMDSH_FileName), av[0], CMDSH_FileName);
  559. } /* do_opencmdshell */
  560.  
  561.  
  562. /*
  563. *!
  564. *! >CMDSHELLOUT text
  565. *!
  566. *!  output to the Commandshell
  567. *!
  568. */
  569. DEFUSERCMD("cmdshellout",   1, CF_COK|CF_ICO|CF_VWM, int, do_cmdshelloutput,  (void), ;)
  570. /*DEFHELP #cmd commandshell CMDSHELLOUT txt - output a string to the command shell */
  571. Prototype int do_cmdshelloutput (void);
  572. int do_cmdshelloutput (void) {
  573.     return CMDSH_Error(CMDSH_Print("%s\n", (ULONG *)&av[1]), av[0]);
  574. } /* do_cmdshelloutput */
  575.  
  576.  
  577.  
  578.  
  579. /*DEFLONG #long COMMANDSHELL
  580.  
  581. That Package allows use of an ansynchroneous Commandshell,
  582. a simple Console window to type commands into.
  583.  
  584. Most aspects of that package can be controlled via variables,
  585. but there are also 3 commands:
  586.  
  587.     OPENCMDSHELL - makes the commandshell appear;
  588.  
  589.     CLOSECMDSHELL - makes the commandshell dissappear;
  590.  
  591.     CMDSHELLOUT text - write some to the commandshell
  592.  
  593. the following special variables complete the package:
  594.  
  595.     $cmdshell - (BOOL) the status of the commandshell;
  596.      setting it to "1" makes the Commandshell open,
  597.      setting it to "0" makes the Commandshell close.
  598.  
  599.     $cmdshellfile - (FILE) the file to be used for the commandshell;
  600.     that file _must_ be interactive.
  601.     plase note, that modification of that variable currently
  602.     only has effect after the NEXT open of the commandshell,
  603.     the active commandshell is not changed.
  604.     Defaults to "CON:0/11/640/60/XDME Command Shell/Close".
  605.  
  606.     $cmdshellprompt - (STRING) the string to displayed to signal
  607.     the user, that he can enter a command;
  608.     plase note, that modification of that variable currently
  609.     only has effect after the NEXT update of the prompt,
  610.     i.e. after the next time, something was written to the
  611.     commandshell, or the user pressed return in the cmdshell;
  612.     the active prompt is not changed.
  613.     The prompt is expanded (via variable-expansion) each time,
  614.     it is displayed
  615.     Defaults to "`XDME> "
  616.  
  617.     $errorsoncmdshell - (BOOL) as long as that flag is set, and
  618.     the commandshell is open, all errors are dispayed on the
  619.     commandshell.
  620.  
  621.     $warningsoncmdshell - (BOOL) as long as that flag is set, and
  622.     the commandshell is open, all warnings are dispayed on the
  623.     commandshell.
  624.  
  625. */
  626.  
  627. #undef STATIC_COM
  628. /***********************************************************
  629.     The STATIC_COM section has currently _2_ purposes:
  630.       - first of all it is designed to allow modules
  631.     that need no references from the main application
  632.     and so can be used just by adding them to the
  633.     source tree of a tool
  634.       - to achieve that goal we have 2 possibilities:
  635.     - we can use the "COMMAND(...)" lines to generate
  636.       a List of all commands of a certain application,
  637.       (static solution)
  638.     - we can add AUTOINIT and AUTOEXIT functions
  639.       which add those COMMAND lines to a global
  640.       database themselfes (dynamic solution)
  641.       that way is very interesting in case of using
  642.       a split application, cluttered in many small
  643.       modules, which can be activated or removed
  644.       by user request
  645.  
  646.     Since Dynamic method means too much overhead to be of
  647.     any use for the XDME, we will probably probably never
  648.     use the DYNAMIC solution, and for that reason it might
  649.     be of more use to put those command lines to the
  650.     functions, which implement those commands.
  651. ***********************************************************/
  652. #ifdef STATIC_COM
  653.  
  654.     COMMAND("closecmdshell",  0, CF_COK|CF_ICO|CF_VWM, (FPTR)do_closecmdshell )
  655.     COMMAND("opencmdshell",   0, CF_COK|CF_ICO|CF_VWM, (FPTR)do_opencmdshell  )
  656.     COMMAND("cmdshellout",    1, CF_COK|CF_ICO|CF_VWM, (FPTR)do_cmdshelloutput)
  657.  
  658.     DEFFLAG( 94-09-21, CMDSH_Active, 0 )
  659.     DEFFLAG( 94-09-21, CMDSH_WarningsOut, 0 )
  660.     DEFFLAG( 94-09-21, CMDSH_ErrorsOut, 0 )
  661.  
  662. #endif
  663.  
  664. #undef SPC_VAR
  665. /***********************************************************
  666.     The SPC_VAR section has only one purpose:
  667.       - it contains descriptions for all special
  668.     variables of the module, which are of interest
  669.     for the user - to change them or to ask their
  670.     values via variable interface.
  671.     that section shall _never_ be considered C-Source
  672.     (for that reason the "#undef" is put just before)
  673.     but it is scanned by an external parser in order
  674.     to produce a list of all Special variables and
  675.     their access functions in a seperate File.
  676. ***********************************************************/
  677. #ifdef SPC_VAR
  678.  
  679. generic global bit cmdshell = %{
  680.     reference = "CMDSH_Active";
  681.     set       = %[ { char inter; inter = test_arg(value, $(REFERENCE)); if (inter != $(REFERENCE)) if (inter) do_opencmdshell(); else do_closecmdshell(); } %];
  682.     help      = %[ the IsOpen status of the CommandShell; %];
  683.     gendate   = "13-09-94/1";
  684.     initval   = "0";
  685. %};
  686.  
  687. generic global str cmdshellname = %{
  688.     reference = "CMDSH_FileName";
  689.     set       = %[ $(REFERENCE) = strrep ($(REFERENCE), value); %];
  690.     help      = %[ The filename used for the CommandShell in the next opening; the used file must be interactive, and it must not be a "AUTO" Console window %;
  691.     gendate   = "13-09-94/2";
  692.     initval   = %[ "CON:0/11/640/60/XDME Command Shell/Close" %];
  693. %};
  694.  
  695. generic global str cmdshellprompt = %{
  696.     reference = "CMDSH_Prompt";
  697.     set       = %[ $(REFERENCE) = strrep ($(REFERENCE), value); %];
  698.     help      = %[ the prompt string of the Command Shell %];
  699.     gendate   = "14-09-94/1";
  700.     initval   = %[ "`XDME> " %];
  701. %};
  702.  
  703. generic global bit errorsoncmdshell = %{
  704.     reference = "CMDSH_ErrorsOut";
  705.     help      = %[ Decide if errors shall be displayed on the commandshell; %];
  706.     gendate   = "14-09-94/2";
  707.     initval   = "0";
  708. %};
  709.  
  710. generic global bit warningsoncmdshell = %{
  711.     reference = "CMDSH_WarningsOut";
  712.     help      = %[ Decide if warnings shall be displayed on the commandshell; %];
  713.     gendate   = "14-09-94/3";
  714.     initval   = "0";
  715. %};
  716.  
  717. #endif
  718.  
  719.  
  720. /******************************************************************************
  721. *****  END CMDSH.c
  722. ******************************************************************************/
  723.  
  724.  
  725. /*
  726.  
  727. ACTION_WAIT_FOR_CHAR:
  728.     arg1 = TimeOut -> Res1 = Success, Res2 = NumChars
  729.  
  730. ACTION_FORCE == 2001:
  731.     Arg1 = fh->Arg1? Arg2 = buffer, Arg3 = NumChars -> Res = Success, Res2 = IoErr()
  732. */
  733.  
  734.  
  735.  
  736.  
  737.  
  738. #if 0
  739.  
  740. #define Waited_for ACTION_READ /* ACTION_WAIT_FOR_CHAR */
  741.  
  742. static void collect_pending_writes (void) {
  743.     struct MinNode      *n;
  744.     struct StandardPacket *m;
  745.  
  746.     for (n = GetHead (port); (m = (void *)n);) {
  747.     n = GetSucc (n);
  748.     if (m->sp_Pkt.dp_Type != Waited_for) {
  749.         Remove ((void *)m);
  750.         FreeDosObject (STD_PKT, &m->sp_Pkt);
  751.         -- pending_writes;
  752.     } /* if */
  753.     } /* for */
  754. } /* collect_pending_writes */
  755.  
  756. void reprompt (newprompt) {
  757.  
  758.     collect_pending_writes();
  759.  
  760.     if (strcmp (newprompt, prompt) == 0)
  761.     return;
  762.  
  763.     strcpy (prompt, newprompt);
  764.  
  765.     if (!Pending) {
  766.     fwrite (\r);
  767.     fwrite (prompt);
  768.     } else {
  769.     check_for_pending_read();
  770.     mySendIO( ACTION_FORCE, 1, EOF );
  771.  
  772.     wait_for_pending_read();
  773.     fwrite (\r);
  774.     fwrite (prompt);
  775.  
  776.     mySendIO (ACTION_FORCE, recently_read_chars);
  777.     mySendIO (ACTION_WAIT);
  778.     } /* if */
  779.  
  780. }
  781.  
  782.  
  783. #endif
  784.